
struct OTreeNode {
  struct OTreeNode * parent;
  struct List nodes;
  struct List dbObjects;
  
  void * metaData;
}

// User specifies OTreeNode.classify

#define THIS = -1;
#define NONE = -2;

int OTreeNode_classify(OTreeNode * node, void * object);

boolean insert(OTreeNode * node, void * object) {
  int class = OTreeNode_classify(node, object);

  if(class == THIS) {
    return List_add(dbObjects, object);
  } else if(class == NONE) {
    return insert(new_child(node, object), object);
  } else {
    return insert(List_get(nodes, class), object);
  }
}

boolean contains(OTreeNode * node, void * object) {
  int class = OTreeNode_classify(node, object);
  
  if(class == THIS) {
    return List_contains(dbObjects, object);
  } else if(class == NONE) {
    return false;
  } else {
    return contains(List_get(nodes, class), object);
  }
}

boolean couldContain(OTreeNode * node, void * object) {
  return OTreeNode_classify(node, object) == NONE;
}

boolean remove(OTreeNode * node, void * object) {
  int class = OTreeNode_classify(node, object);
  
  if(class == THIS) {
    return List_remove(dbObjects, object);
  } else if(class == NONE) {
    return false;
  } else {
    return remove(List_get(nodes, class), object);
  }
}

tree query(OTreeNode * node, void* range) {
  int[] classs = OTreeNode_classifyRange(node, range);

  if(class[0] == NONE) {
    return NULL_TREE;
  } else {
    tree = new tree(range);
    if(class[0] == THIS) {
      tree.add(node);
    }
    for(int i = 1; i < class.length; i++) {
      tree.add(query(List_get(nodes, class[i]), range));
    }
  }
}

iterator iterator() { ... }

List dbObjects(OTreeNode * node) {
  return dbObjects;
}
